package com.example.demo.auth.service;

import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.auth.dao.LoginDao;
import com.example.demo.core.DefineConstant;
import com.example.demo.entity.LoginEnity;
import com.example.demo.entity.LoginRole;
import com.example.demo.entity.base.ResponseEntity;
import com.example.demo.util.CookieUtil;
import com.example.demo.util.DateUtil;
import com.example.demo.util.EmptyUtil;
import com.example.demo.util.EncryUtil;
import com.example.demo.util.JWTUtil;
import com.example.demo.util.PropertiesUtil;
import com.example.demo.util.RSAUtil;
import com.example.demo.util.RedisUtil;
import com.example.demo.util.ResponseFactory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class LoginService {
	
	@Autowired
	private LoginDao loginDao;
	
	@Autowired
	private RedisUtil redisUtil;
	
	/**
	 * 登陆验证接口
	 * @param logininfo
	 * @param response 
	 * @param request 
	 * @return
	 */
	public ResponseEntity<String> logOn(LoginEnity logininfo, HttpServletResponse response, HttpServletRequest request) {
		String oldtoken = logininfo.getToken();
		
		if(EmptyUtil.isNotEmpty(oldtoken)) {
			try {
				redisUtil.remove(oldtoken);
			} catch (Exception e) {
				log.error("删除原来登陆得用户令牌失败",e);
				return ResponseFactory.setFail("删除原来登陆得用户令牌失败");
			}
		}
		
		if(EmptyUtil.isEmpty(logininfo)) {
			log.error("未输入登陆信息");
			return ResponseFactory.setFail("未输入登陆信息");
		}
		
		if(EmptyUtil.isEmpty(logininfo.getLogin_id())) {
			log.error("未输入登陆账号");
			return ResponseFactory.setFail("未输入登陆账号");
		}
		
		if(EmptyUtil.isEmpty(logininfo.getLogin_password())) {
			log.error("未输入登陆密码");
			return ResponseFactory.setFail("未输入登陆密码");
		}
		
		String rsaPubKey = logininfo.getRsaPubKey();
		
		if(EmptyUtil.isEmpty(rsaPubKey)) {
			return ResponseFactory.setFail("未获取到加密公钥");
		}
		
		String rsaPrivateKey;
		
		try {
			rsaPrivateKey = redisUtil.getValue(DefineConstant.RSA_PUB_KEY_PRE+rsaPubKey);
		} catch (Exception e) {
			log.error("获取私钥失败",e);
			return ResponseFactory.setFail("获取私钥失败");
		}
		
		if(EmptyUtil.isEmpty(rsaPrivateKey)) {
			return ResponseFactory.setFail("私钥已过期,请刷新页面");
		}
		
		//RSA解密
		String decodePasswd;
		
		try {
			decodePasswd = RSAUtil.decrypt(logininfo.getLogin_password(), rsaPrivateKey);
		} catch (Exception e) {
			log.error("解密密码失败",e);
			return ResponseFactory.setFail("解密密码失败");
		}
		
		logininfo.setLogin_password(decodePasswd);
		
		String encrypPwd;
		try {
			encrypPwd = EncryUtil.encrypt(logininfo.getLogin_password(), DefineConstant.ENCRYKEY);
		} catch (Exception e) {
			log.error("密码加密失败",e);
			return ResponseFactory.setFail("密码加密失败");
		}
		
		logininfo.setLogin_password(encrypPwd);
		
		List<LoginEnity> loginsDomain = null;
		
		try {
			loginsDomain = loginDao.verifiyLogin(logininfo);
		} catch (Exception e) {
			log.error("验证登陆信息失败",e);
			return ResponseFactory.setFail("验证登陆信息失败");
		}
		
		if(EmptyUtil.isEmpty(loginsDomain)) {
			return ResponseFactory.setFail("您输入的账号不存在");
		}
		
		if(loginsDomain.size()>1) {
			return ResponseFactory.setFail("此账号重复注册，请联系管理员");
		}
		
		if(!logininfo.getLogin_password().equals(loginsDomain.get(0).getLogin_password())) {
			return ResponseFactory.setFail("您输入的密码不正确");
		}
		
		if(EmptyUtil.isEmpty(loginsDomain.get(0).getAllow_login())||!(DefineConstant.ALLOWLOGIN==loginsDomain.get(0).getAllow_login())) {
			return ResponseFactory.setFail("无登陆权限");
		}
		
		LoginEnity userinfo = loginsDomain.get(0);
		
		LoginEnity logintime = new LoginEnity();
		
		logintime.setLogin_id(userinfo.getLogin_id());
		logintime.setLast_login_time(DateUtil.getNowDateTime());
		
		try {
			loginDao.updateLoginUserInfo(logintime);
		} catch (Exception e) {
			log.error("修改登陆时间失败",e);
			return ResponseFactory.setFail("修改登陆时间失败");
		}
		
		//获取登陆账号得角色
		List<LoginRole> loginRoles = null;
		
		try {
			loginRoles = loginDao.getLoginRoles(userinfo.getLogin_id());
		} catch (Exception e) {
			log.error("获取用户登陆角色失败");
			return ResponseFactory.setFail("获取用户登陆角色失败");
		}
		
		if(EmptyUtil.isEmpty(loginRoles)) {
			return ResponseFactory.setFail("用户未配置角色");
		}
		
		//把用户角色放入登陆实体类,储存到redis缓存中
		userinfo.setLogin_roles(loginRoles);
		
		String userinfostr = JSONObject.toJSONString(userinfo);
		
		String token = JWTUtil.createToken(userinfo);
		
		String tokenTimeOut = PropertiesUtil.getProperty("tokenTimeOut");
		
		//将token添加到cookie内
		Cookie cookie_token = new Cookie(DefineConstant.AUTH_TOKEN_NAME, token);
		String contextPath = request.getContextPath();
		cookie_token.setPath(EmptyUtil.isEmpty(contextPath)?"/":contextPath);
		response.addCookie(cookie_token);
		
		try {
//			redisUtil.addString(token, userinfostr, Long.parseLong(tokenTimeOut));
			
			redisUtil.setToken(token, userinfostr, Long.parseLong(tokenTimeOut));
		} catch (NumberFormatException e) {
			log.error("超时时间转换异常",e);
			TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
			return ResponseFactory.setFail("超时时间转换异常");
		} catch (Exception e) {
			log.error("将token保存至redis失败",e);
			TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
			return ResponseFactory.setFail("将token保存至redis失败");
		}
		
		return ResponseFactory.setSuccess(token, "登陆成功!");
	}
	
	/**
	 * @param response 
	 * @return
	 * @创建时间: 2019年8月30日
	 * @创建人: 许子文
	 * @功能描述: 登出,清除登陆状态
	 */
	public ResponseEntity<String> logOut(String token, HttpServletResponse response) {
		if(EmptyUtil.isEmpty(token)) {
			return ResponseFactory.setFail("token已过时");
		}
		
		try {
			redisUtil.removeToken(token);
		} catch (Exception e) {
			log.error("清除redis中的登陆数据失败",e);
			return ResponseFactory.setFail("清除redis中的登陆数据失败");
		}
		
		//清除cookie
		CookieUtil.removeCookie(response, DefineConstant.AUTH_TOKEN_NAME);
		
		return ResponseFactory.setSuccess("已清除登陆状态");
	}
	
	/**
	 * 
	 * @title getRsaPubKey
	 * @author: 许子文
	 * @date: 2021年6月4日
	 * @description: 生成RSA密钥对,并提供公钥给前端
	 *
	 */
	public ResponseEntity<String> getRsaPubKey(){
		
		String coupleKey = null;
		
		try {
			coupleKey = RSAUtil.genKeyPair();
		} catch (Exception e) {
			log.error("生成密匙对失败",e);
			return ResponseFactory.setFail("生成密匙对失败");
		}
		
		String[] keys = coupleKey.split(":");
		
		String publicKey = keys[0];
		String privateKey = keys[1];
		
		try {
			//密匙对保存5分钟
			redisUtil.addString(DefineConstant.RSA_PUB_KEY_PRE+publicKey, privateKey, 300L);
		} catch (Exception e) {
			log.error("保存密匙对失败",e);
			return ResponseFactory.setFail("保存密匙对失败");
		}
		
		return ResponseFactory.setObject(publicKey);
	}
}
